#pragma once

#include <iostream>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include "include/Log.hpp"
#include "Connection.hpp"
#include "Common.hpp"
#include "EventHandler.hpp"

class Accepter
{
public:
    Accepter()
    {}

    void accept(Connection* conn)
    {
        while(true) //ET模式，循环读
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int connect_fd = ::accept(conn->getSockFd(), (struct sockaddr*)&peer, &len);
            if(connect_fd > 0)
            {
                char buffer[64];
                inet_ntop(AF_INET, &peer.sin_addr, buffer, sizeof(buffer));
                conn->setClientIp(buffer);
                conn->setClientPort(ntohs(peer.sin_port));
                log.message(INFO, "get a new link, fd: %d", connect_fd);

                setNonBlock(connect_fd);
                auto reader = std::bind(&EventHandler::read, std::placeholders::_1);
                auto writer = std::bind(&EventHandler::write, std::placeholders::_1);
                auto excepter = std::bind(&EventHandler::except, std::placeholders::_1);
                conn->_svrFrom->addConnection(ConnectionFactory::createNormalConnection(
                    connect_fd, reader, writer, excepter, EPOLLIN|EPOLLET, conn->_svrFrom));
            }
            else
            {
                if(errno == EAGAIN) break; //数据取尽，无数据就绪
                else if(errno == EINTR) continue; //上次读取被信号中断
                else //发生错误
                {
                    log.message(WARN, "accept socket error... %d: %s", errno, strerror(errno));
                    break;
                }
            }
        }
    }

    ~Accepter()
    {}
};